package pfq.demo.rx;

import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.TextView;

import java.util.concurrent.TimeUnit;

import androidx.appcompat.app.AppCompatActivity;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import pfq.demo.R;

/**
 * 演示了使用RxJava优化搜索联想功能
 * <p>
 * 我们要达到的效果是：当用户输入完之后才发起网络请求，而不是直接在afterTextChanged中每次收到回调都发
 * <p>
 * 我记得在金融圈的时候就遇到过这样的需求，当时的处理是用handler做了一个延时处理，并发送当时搜索的字符串，然后再onHandle方法中判断是否与此刻的输入框字符串内容一致，如果一致则发起请求，因为有可能用户在延时的这段时间里修改了内容
 * <p>
 * 当然代码量不算多，但只要用handler就不可避免的看着有点乱，所以可以使用RxJava的debounce操作符来代替，代码看着会舒服点儿，也简单很多
 */
public class SearchOptActivity extends AppCompatActivity {


    private TextView mSearchResultTextView;

    private PublishSubject<String> mPublishSubject;
    private DisposableObserver<String> mDisposableObserver;
    private CompositeDisposable mCompositeDisposable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rx_search);

        mSearchResultTextView = (TextView) findViewById(R.id.searchResultTextView);

        EditText searchEditText = (EditText) findViewById(R.id.searchEditText);
        searchEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                startSearch(s.toString());
            }
        });

        mPublishSubject = PublishSubject.create();
        mDisposableObserver = new DisposableObserver<String>() {
            @Override
            public void onNext(String s) {
                mSearchResultTextView.setText("完成搜索，关键字：" + s);

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        };
        mPublishSubject.debounce(200, TimeUnit.MILLISECONDS).filter(new Predicate<String>() {
            @Override
            public boolean test(String s) throws Exception {
                return s.length() > 0;
            }
        }).switchMap(new Function<String, ObservableSource<String>>() {
            @Override
            public ObservableSource<String> apply(String s) throws Exception {
                return getSearchObservable(s);
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(mDisposableObserver);

        mCompositeDisposable = new CompositeDisposable();
        mCompositeDisposable.add(mDisposableObserver);
    }


    private void startSearch(String value) {
        mPublishSubject.onNext(value);
    }

    private Observable<String> getSearchObservable(final String query) {
        return Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                Thread.sleep(100 + (long) Math.random() * 500);

                e.onNext(query);
                e.onComplete();
            }
        }).subscribeOn(Schedulers.io());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mCompositeDisposable.clear();
    }
}
